#include "utility.h"
#include <QTextCodecPlugin>
#include <QByteArray>
#include <QLocale>
#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Node>
#include <osg/Group>
#include <osg/AnimationPath>
#include <assert.h>
#include <osg\Geometry>
//#include <sstream>

bool _boolIsOutdoor;

QTextCodec* ChineseTextCodec::m_pChineseCodec = NULL;

void ChineseTextCodec::SetChineseCodecPluginObject(QObject* plugin)
{
      QTextCodecPlugin* pCodecPlugin = dynamic_cast<QTextCodecPlugin*>(plugin);
	  if(pCodecPlugin)
	  {
		  m_pChineseCodec = pCodecPlugin->createForName("GBK");
	  }
}

QTextCodec* ChineseTextCodec::GetChineseCodec()
{
     if (m_pChineseCodec==NULL)
     {
		 m_pChineseCodec = QTextCodec::codecForName("GBK");
     }
	 return m_pChineseCodec;
}

std::string ChineseTexttoStdstring(const QString& strChinese,bool bConvertOnlyInChineseLanguageSystem)
{
	if(bConvertOnlyInChineseLanguageSystem)
	{
		if(QLocale::system().language() != QLocale::Chinese)
		{
			return strChinese.toStdString();
		}
	}

	QTextCodec *codec = ChineseTextCodec::GetChineseCodec();
	if (codec)
	{
		QByteArray gbkString = codec->fromUnicode(strChinese);
		std::string strstd = gbkString.data();
		return strstd;
	}
	else
	{
        return strChinese.toStdString();
	}
}

void setOsgNodeMask(osg::Node* node,unsigned int mask)
{
	osg::Geode* geode = node->asGeode();
	if(geode)
	{
		geode->setNodeMask(mask);
		return;
	}
	QList<osg::Group*> listgroup;
	osg::Group* pgroup = node->asGroup();
	if(pgroup)
	{
		pgroup->setNodeMask(mask);
        listgroup.push_back(pgroup);
	}
	while(listgroup.size()>0)
	{
		osg::Group* pFrontGroup = listgroup.front();
		listgroup.pop_front();
		int nNode = pFrontGroup->getNumChildren();
		for(int i=0; i<nNode; i++)
		{
			node = pFrontGroup->getChild(i);
			osg::Geode* geode = node->asGeode();
			if(geode)
			{
				geode->setNodeMask(mask);
			}
			else
			{
				osg::Group* pgroup = node->asGroup();
				if(pgroup)
				{
					pgroup->setNodeMask(mask);
					listgroup.push_back(pgroup);
				}
			}			
		}
	}
}

int getTextWidth(int textsize,const QString& text)
{
	int size = 0;
	for(int i = 0;i<text.size();i++)
	{
		QChar car = text.data()[i];
		if(car > 0x80)
		{
			size = size+2;
		}
		else
		{
			size++;
		}
	}
	return size*textsize/2;
}

void formatText(const QString& text,int charactercount,QVector<QString>& returntext)
{
	int textsize = 0;
	for(int i = 0;i<text.size();i++)
	{
		QChar car = text.data()[i];
		if(car > 0x80)
		{
			textsize = textsize+2;
		}
		else
		{
			textsize++;
		}
	}
	if(textsize > charactercount)
	{
		QString returntext1 = "";
		textsize = 0;
		for(int i = 0;i<text.size();i++)
		{
			QChar car = text.data()[i];
			if(car > 0x80)
			{
				textsize = textsize+2;
			}
			else
			{
				textsize++;
			}
			returntext1.append(car);
			if(textsize + 2 >= charactercount)
			{
				returntext.push_back(returntext1);
				textsize = 0;
				returntext1 = "";
			}
		}
		if(returntext1!="")
			returntext.push_back(returntext1);
	}
	else
	{
		returntext.push_back(text);
	}
}

void foundChildStateSet(osg::Node* node,QVector<osg::ref_ptr<osg::Material>>& vec)
{
	if(!node->asGroup())
	{
		if(node->getStateSet()!=NULL)
			vec.push_back((osg::Material*)node->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
		if(node->asGeode())
		{
			osg::Geode* geode = node->asGeode();
			osg::Geode::DrawableList list = geode->getDrawableList();
			for(int i=0;i<list.size();++i)
			{
				if(list.at(i)->getStateSet()!=NULL)
					vec.push_back((osg::Material*)list.at(i)->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
			}
		}
		return;
	}
	QList<osg::Group*> listgroup;
	osg::Group* group = node->asGroup();
	listgroup.push_back(group);
	if(node->getStateSet()!=NULL)
		vec.push_back((osg::Material*)node->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
	while(listgroup.size()>0)
	{
		osg::Group* frontgroup = listgroup.front();
		listgroup.pop_front();
		int num = frontgroup->getNumChildren();
		for(int j=0; j<num;++j)
		{
			node = frontgroup->getChild(j);
			if(!node->asGroup())
			{
				if(node->getStateSet()!=NULL)
					vec.push_back((osg::Material*)node->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
				if(node->asGeode())
				{
					osg::Geode* geode = node->asGeode();
					osg::Geode::DrawableList list = geode->getDrawableList();
					for(int i=0;i<list.size();++i)
					{
						if(list.at(i)->getStateSet()!=NULL)
							vec.push_back((osg::Material*)list.at(i)->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
					}
				}
			}
			else
				listgroup.push_back(node->asGroup());		
		}
	}
}
//std::string& stringtrim(std::string &s) 
//{
//	if(s.empty()) 
//	{
//		return s;
//	}
//	s.erase(0,s.find_first_not_of(" "));
//	s.erase(s.find_last_not_of(" ") + 1);
//	return s;
//}

void composeNumberFromHandL(int& num,int hv,int lv)
{
	QVector<int> heightvec;
	QVector<int> lowvec;
	num = 0;
	int h = hv;
	while(h>=2)
	{
		heightvec.push_back(h%2);
		h = h/2;
	}
	heightvec.push_back(h);
	int l = lv;
	while(l>=2)
	{
		lowvec.push_back(l%2);
		l = l/2;
	}
	lowvec.push_back(l);
	for(int i=0;i<heightvec.size();++i)
	{
		num = num + heightvec.at(i)*pow(2.0f,(16+i));
	}
	for(int i=0;i<lowvec.size();++i)
	{
		num = num + lowvec.at(i)*pow(2.0f,i);
	}
}

void splitNumberToHandL(int num,int& h,int& l)
{
	QVector<int> vec;
	h = 0;
	l = 0;
	int n = num;
	while(n>=2)
	{
		vec.push_back(n%2);
		n = n/2;
	}
	vec.push_back(n);
	int size = vec.size();
	if(size>8)
	{
		for(int i=0;i<8;++i)
		{
			l = l+ vec.at(i)*pow(2.0f,i);
		}
		for(int i=8;i<size;++i)
		{
			h = h+ vec.at(i)*pow(2.0f,i-16);
		}
	}
	else
	{
		for(int i=0;i<size;++i)
		{
			l = l+ vec.at(i)*pow(2.0f,i);
		}
	}
}

bool pointInTriangle(const osg::Vec2& tripoint1,const osg::Vec2& tripoint2,
								const osg::Vec2& tripoint3,const osg::Vec2& point)
{
	float z = (point.x() - tripoint1.x())*(tripoint2.y() - tripoint1.y()) - (tripoint2.x() - tripoint1.x())*(point.y() - tripoint1.y());
	z = z/((tripoint3.x() - tripoint1.x())*(tripoint2.y() - tripoint1.y())- (tripoint2.x() - tripoint1.x())*(tripoint3.y() - tripoint1.y()));
	float y = (point.x() - tripoint1.x() - (tripoint3.x() - tripoint1.x())*z)/(tripoint2.x() - tripoint1.x());
	float x = 1 - y - z;
	if(x>0 && y>0 && z>0)
		return false;
	else
		return true;
}

bool shapeIsCounterclockwise(std::vector<osg::Vec3> vertexvector)
{
	int resultvalue = 0;
	for(int i=0;i<vertexvector.size()-1;++i)
	{
		osg::Vec3 p3;
		if(i+2==vertexvector.size())
			p3 = vertexvector.at(0);
		else
			p3 = vertexvector.at(i+2);
		osg::Vec3 v1 = vertexvector.at(i+1) - vertexvector.at(i);
		osg::Vec3 v2 = p3 - vertexvector.at(i+1);
		osg::Vec3 result = osg::Vec3(v1.x(),v1.y(),0)^osg::Vec3(v2.x(),v2.y(),0);
		if(result.z()>0)
			resultvalue++;
		else
			resultvalue--;
	}
	return resultvalue>0;
}

QString getPreOrderString(int order)
{
	QString os = QString::number(order);
	while(os.size()<6)
	{
		os = "0"+os;
	}
	return os;
}

void getVUValue(osg::Vec3 normal ,osg::Vec3& mu,osg::Vec3& mv)
{
	normal.normalize();
	if(abs(normal.x())>=abs(normal.y()))
	{
		mu.x() = normal.z();
		mu.y() = 0;
		mu.z() = normal.x()*-1;
	}
	else
	{
		mu.x() = 0;
		mu.y() = normal.z();
		mu.z() = normal.y()*-1;
	}
	mv = normal^mu;
}

//std::vector<osg::Vec3> getExpandPointVec(const osg::Vec3 centerpoint,float radius,int facenum
//																 ,const osg::Vec3 mu,const osg::Vec3 mv)
//{
//	std::vector<osg::Vec3> mvec;
//	for(int i=0;i<facenum;i++)
//	{
//		float angle = i*osg::PI*2/facenum;
//		osg::Vec3 point = centerpoint+mu*(radius*cos(angle)) + mv*(radius*sin(angle));
//		mvec.push_back(point);
//	}
//	return mvec;
//}

double conversionDMS_TO_D(int d,int m,int s)
{
	double result = d;
	double v = m*60+s;
	result = result + v/3600.00;
	return result;
}

double conversionDM_TO_D(int d,double m)
{
	double result = d;
	result = result + m/60.00;
	return result;
}

void conversionD_TO_DMS(double dv,int& d,int& m,int& s)
{
	d = dv;
	m = (dv-d)*3600/60;
	s = (int)((dv-d)*3600)%60;
}

//void sortNum(std::vector<float>& vec,int start,int end)
//{
//	if(start>=end)
//		return;
//	float key = vec.at(start);
//	int i=start;
//	int j=end;
//	while(i!=j)
//	{
//		while(i!=j)
//		{
//			if(vec.at(j)<key)
//			{
//				float ival = vec[i];
//				vec[i] = vec[j];
//				vec[j] = ival;
//				break;
//			}
//			j--;
//		}
//		while(i!=j)
//		{
//			if(vec.at(i)>key)
//			{
//				float jval = vec[j];
//				vec[j] = vec[i];
//				vec[i] = jval;
//			}
//			i++;
//		}
//	}
//	sortNum(vec,start,i-1);
//	sortNum(vec,i+1,end);
//}
//
//void sortNumVec3(std::vector<osg::Vec3>& vec,int index,int start,int end)
//{
//	if(start>=end)
//		return;
//	float key = vec.at(start)._v[index];
//	int i=start;
//	int j=end;
//	while(i!=j)
//	{
//		while(i!=j)
//		{
//			if(vec.at(j)._v[index]<key)
//			{
//				osg::Vec3 ival = vec[i];
//				vec[i] = vec[j];
//				vec[j] = ival;
//				break;
//			}
//			j--;
//		}
//		while(i!=j)
//		{
//			if(vec.at(i)._v[index]>key)
//			{
//				osg::Vec3 jval = vec[j];
//				vec[j] = vec[i];
//				vec[i] = jval;
//			}
//			i++;
//		}
//	}
//	sortNumVec3(vec,index,start,i-1);
//	sortNumVec3(vec,index,i+1,end);
//}
//
//void sortNumProxy(std::vector<CHTElecComponentActorProxy*>& vec,int index,int start,int end)
//{
//	if(start>=end)
//		return;
//	float key = vec.at(start)->GetTranslation()._v[index];
//	int i=start;
//	int j=end;
//	while(i!=j)
//	{
//		while(i!=j)
//		{
//			if(vec.at(j)->GetTranslation()._v[index]<key)
//			{
//				CHTElecComponentActorProxy* ival = vec[i];
//				vec[i] = vec[j];
//				vec[j] = ival;
//				break;
//			}
//			j--;
//		}
//		while(i!=j)
//		{
//			if(vec.at(i)->GetTranslation()._v[index]>key)
//			{
//				CHTElecComponentActorProxy* jval = vec[j];
//				vec[j] = vec[i];
//				vec[i] = jval;
//			}
//			i++;
//		}
//	}
//	sortNumProxy(vec,index,start,i-1);
//	sortNumProxy(vec,index,i+1,end);
//}
//
////----------------------------------------------------------------------------------------------------------------------
////kinds of data-type convert to std::string
////----------------------------------------------------------------------------------------------------------------------
//std::string stringFrmStrs(std::vector<std::string>& strs, std::string& token)
//{
//	std::string combine ; 
//	for( int i=0; i<strs.size(); i++ )
//	{
//		combine.append( strs[i] ) ;
//		if( i != (strs.size()-1))
//			combine.append( token ) ;
//	}
//	return combine ;
//}
//
//std::vector<std::string> stringToStrs( std::string& strs, std::string& token )
//{
//	std::vector<std::string> splits ;
//	char *tokenPtr ;
//	tokenPtr = strtok( (char*)strs.c_str(), token.c_str() );
//	while( tokenPtr != NULL )
//	{
//		splits.push_back( std::string(tokenPtr) ) ;
//		tokenPtr = strtok( NULL, token.c_str() ) ;
//	}
//
//	return splits ;
//}
//
//std::string stringFrmInt( int value )
//{
//	char buffer[256]={0} ;
//	itoa( value, buffer, 10 ) ;
//	std::string str = buffer ;
//	return str ;
//}
//
//int stringToInt( std::string& str )
//{
//	return atoi( str.c_str() ) ;
//}
//
//std::string stringFrmFloat( float value )
//{
//	char buffer[256]={0} ;
//	sprintf( buffer, "%f", value ) ;
//	std::string str = buffer ;
//	return str ;
//}
//
//float stringToFloat( std::string& str )
//{
//	return atof( str.c_str() ) ;
//}
//
//std::string stringFrmIntArray( int* array,  unsigned int size, std::string& token  )
//{
//	std::vector<std::string> strs ;
//	for( int i=0; i<size; i++ )
//	{
//		strs.push_back( stringFrmInt(array[i]) ) ;
//	}
//	return stringFrmStrs( strs, token ) ;
//}
//
//int* stringToIntArray( std::string& strs, std::string& token , unsigned int& size)
//{
//	std::vector<std::string> splits = stringToStrs( strs, token ) ;
//	if( splits.empty() )
//	{
//		size = 0 ;
//		return NULL ;
//	} else
//	{
//		int* array = new int[splits.size()] ;
//		for( int i=0 ;i<splits.size(); i++ )
//			array[i] = stringToInt( splits[i] ) ;
//		size = splits.size() ;
//		return array ;
//	}	
//}
//
//std::string stringFrmFloatArray( float* array,  unsigned int size, std::string& token  ) 
//{
//	std::vector<std::string> strs ;
//	for( int i=0; i<size; i++ )
//	{
//		strs.push_back( stringFrmFloat(array[i]) ) ;
//	}
//	return stringFrmStrs( strs, token ) ;
//}
//
//float* stringToFloatArray( std::string& strs, std::string& token , unsigned int& size) 
//{
//	std::vector<std::string> splits = stringToStrs( strs, token ) ;
//	if( splits.empty() )
//	{
//		size = 0 ;
//		return NULL ;
//	} else
//	{
//		float* array = new float[splits.size()] ;
//		for( int i=0 ;i<splits.size(); i++ )
//			array[i] = stringToFloat( splits[i] ) ;
//		size = splits.size() ;
//		return array ;
//	}	
//}
//
//std::string stringFrmByteArray( char* array,  unsigned int size, std::string& token )
//{
//	std::string sig, combine ; 
//	std::vector<std::string> splits ;
//	std::stringstream bstream ;
//	for( int i=0; i<size; i++ )
//	{
//		sig = stringFrmInt( array[i] ) ;
//		splits.push_back( sig ) ;
//	}
//	combine = stringFrmStrs( splits, token ) ;
//	return combine ;
//}
//
//char* stringToByteArray( std::string& strs, std::string& token, unsigned int& size )
//{
//	std::stringstream bstream ;
//	std::vector<std::string> splits = stringToStrs( strs, token ) ;
//	if( splits.empty() )
//	{
//		size = 0 ;
//		return NULL ;
//	} else
//	{
//		char* array = new char[splits.size()] ;
//		for( int i=0 ;i<splits.size(); i++ )
//		{
//			array[i] = stringToInt( splits[i] ) ;
//		}
//		size = splits.size() ;
//		return array ;
//	}	
//}
//
//std::string stringFrmBinaryArray( char* binary,  unsigned int size,  std::string& token, std::string& token1 )
//{
//	std::vector<std::string> splits ;
//	splits.push_back( stringFrmInt( size ) );
//	char* copybinary = new char[size+1] ;
//	memcpy( copybinary, binary, size ) ;
//	copybinary[size] = 0 ;
//	int convertSize = 0 ;
//	while( convertSize < size )
//	{
//		std::string str_v = copybinary+convertSize ;
//		if( !str_v.empty() )
//		{
//			std::string str_s = stringFrmInt( convertSize ) ;
//			str_s.append( token1 ) ;
//			str_s.append( str_v ) ;
//			splits.push_back( str_s ) ;
//		}
//		convertSize += str_v.length()+1 ;
//	}
//	std::string combine = stringFrmStrs( splits, token ) ;
//	return combine ;
//}
//
//char* stringToBinaryArray( std::string& strs, std::string& token, std::string& token1, unsigned int& osize )
//{
//	std::vector<std::string> splits = stringToStrs( strs, token ) ;
//	if( splits.empty() )
//	{
//		goto END ;
//	}
//	else
//	{
//		int size = stringToInt( splits[0] ) ;
//		if( size <=0 ) 
//			goto END ;
//		unsigned int location ;
//		char* array = new char[size] ;
//		memset( array, 0, size ) ;
//		for( int i=1 ;i<splits.size(); i++ )
//		{
//			std::vector<std::string> splits_v = stringToStrs( splits[i], token1) ;
//			if( splits_v.size() != 2 )
//				return NULL ;
//			location = stringToInt( splits_v[0] ) ;
//			if( (location+splits_v[1].length())>size )
//				goto END ;
//			memcpy( (char*)(array+location), splits_v[1].c_str(), splits_v[1].length() ) ;
//		}
//		osize = size ;
//		return array ;
//	}	
//END:
//	osize = 0 ;
//	return NULL ;
//}
//
/////base64 encode/decode//////////////////////////////////////////////////////////////////////////
//char base64StringHandler::_basis64[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
//																			   'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
//																			   '0','1','2','3','4','5','6','7','8','9','+','/'} ;
//signed char base64StringHandler::_index64[128] = {	
//	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,	
//	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,	
//	-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,	
//	52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,	
//	-1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,	
//	15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,	
//	-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,	
//	41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1	
//} ;
//
//char base64StringHandler::char64( char c)
//{
//	char result = (((c) < 0 || (c) > 127) ? -1 : _index64[(c)]) ; 
//	if( result == -1 )
//		int mm = 1 ;
//	return result ;
//}
//
//char* base64StringHandler::base64Encode( const unsigned char* value, int vlen ) 
//{
//	unsigned char oval = 0 ; 	
//	char *result = new char[((vlen * 4) / 3 + 5)] ;	
//	memset( result, 0, ((vlen * 4) / 3 + 5) ) ;
//	char *out = result;	
//	while (vlen >= 3) 
//	{	
//		*out++ = _basis64[value[0] >> 2];	
//		*out++ = _basis64[((value[0] << 4) & 0x30) | (value[1] >> 4)];	
//		*out++ = _basis64[((value[1] << 2) & 0x3C) | (value[2] >> 6)];	
//		*out++ = _basis64[value[2] & 0x3F];	
//		value += 3;	
//		vlen -= 3;	
//	}
//	if (vlen > 0) 
//	{	
//		*out++ = _basis64[value[0] >> 2];	
//		oval = (value[0] << 4) & 0x30 ;	
//		if (vlen > 1) oval |= value[1] >> 4;	
//		*out++ = _basis64[oval];	
//		*out++ = (vlen < 2) ? '=' : _basis64[(value[1] << 2) & 0x3C];	
//		*out++ = '=';	
//	}	
//	*out = '\0';		
//	return result;	
//}
//
//char* base64StringHandler::base64Decode( const char* value, int *rlen ) 
//{
//	int c1, c2, c3, c4;	        	
//	int vlen = strlen(value);	
//	char *result = new char[((vlen * 3) / 4 + 1)];	
//	memset( result, 0, ((vlen * 3) / 4 + 1) ) ;
//	unsigned char *out = (unsigned char*)result;	
//	*rlen = 0;
//	while (1) 
//	{	
//		if (value[0]==0) 
//		{
//			*out = '\0' ; 
//			return result;	
//		}
//		c1 = value[0];	
//		if (char64(c1) == -1) 
//			goto base64_decode_error;
//		c2 = value[1];	
//		if (char64(c2) == -1) 
//			goto base64_decode_error;
//		c3 = value[2];	
//		if ((c3 != '=') && (char64(c3) == -1)) 
//			goto base64_decode_error;
//		c4 = value[3];	
//		if ((c4 != '=') && (char64(c4) == -1)) 
//			goto base64_decode_error;	
//		value += 4;	
//		*out++ = (char64(c1) << 2) | (char64(c2) >> 4);	
//		*rlen += 1;	
//
//		if (c3 != '=') 
//		{	
//			*out++ = ((char64(c2) << 4) & 0xf0) | (char64(c3) >> 2);	
//			*rlen += 1;	
//			if (c4 != '=') 
//			{	
//				*out++ = ((char64(c3) << 6) & 0xc0) | char64(c4);	
//				*rlen += 1;	
//			}
//		}	
//	//	count += 4 ;
//	}	
//base64_decode_error:	
//	*result = 0;	
//	*rlen = 0;	
//	return result;	
//}